package com.campuscarbooking.api.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * 缓存操作日志切面
 */
@Aspect
@Component
@Slf4j
public class CacheLoggingAspect {

    /**
     * 定义切点 - 所有缓存一致性服务方法
     */
    @Pointcut("execution(* com.campuscarbooking.api.service.impl.CacheConsistencyServiceImpl.*(..))")
    public void cacheConsistencyServicePointcut() {
    }

    /**
     * 定义切点 - Redis操作
     */
    @Pointcut("execution(* org.springframework.data.redis.core.RedisTemplate.*(..))")
    public void redisTemplatePointcut() {
    }

    /**
     * 环绕通知 - 记录缓存一致性服务方法执行情况
     */
    @Around("cacheConsistencyServicePointcut()")
    public Object logCacheConsistencyService(ProceedingJoinPoint joinPoint) throws Throwable {
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        
        log.info("缓存一致性服务方法 [{}] 开始执行, 参数: {}", methodName, args);
        
        long startTime = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long executionTime = System.currentTimeMillis() - startTime;
        
        log.info("缓存一致性服务方法 [{}] 执行完成, 耗时: {} ms", methodName, executionTime);
        
        return result;
    }

    /**
     * 返回通知 - 记录Redis操作返回值
     */
    @AfterReturning(pointcut = "redisTemplatePointcut()", returning = "result")
    public void logRedisTemplateAfterReturning(JoinPoint joinPoint, Object result) {
        String methodName = joinPoint.getSignature().getName();
        
        // 只记录特定的Redis操作
        if (methodName.startsWith("set") || methodName.startsWith("get") || 
            methodName.startsWith("delete") || methodName.startsWith("has")) {
            log.debug("Redis操作 [{}] 执行完成, 返回值: {}", methodName, result);
        }
    }

    /**
     * 异常通知 - 记录Redis操作异常
     */
    @AfterThrowing(pointcut = "redisTemplatePointcut()", throwing = "ex")
    public void logRedisTemplateAfterThrowing(JoinPoint joinPoint, Throwable ex) {
        String methodName = joinPoint.getSignature().getName();
        log.error("Redis操作 [{}] 执行异常: {}", methodName, ex.getMessage(), ex);
    }
} 